package org.example.springgobang.model;

import lombok.Data;

@Data
public class AIPlayer {
    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    private int[][] board;

    public AIPlayer(int[][] board) {
        this.board = board;
    }

    // 获取AI的最佳落子位置
    public int[] getBestMove() {
        int bestScore = Integer.MIN_VALUE;
        int[] bestMove = {7, 7}; // 默认中心位置

        // 遍历所有可能的位置
        for (int i = 0; i < MAX_ROW; i++) {
            for (int j = 0; j < MAX_COL; j++) {
                if (board[i][j] == 0) { // 空位置
                    // 1. 先检查是否能直接获胜
                    if (isWinningMove(i, j, 2)) {
                        return new int[]{i, j};
                    }

                    // 2. 检查是否需要阻止对手获胜
                    if (isWinningMove(i, j, 1)) {
                        return new int[]{i, j};
                    }

                    // 3. 评估这个位置的分数
                    int score = evaluatePosition(i, j);
                    if (score > bestScore) {
                        bestScore = score;
                        bestMove[0] = i;
                        bestMove[1] = j;
                    }
                }
            }
        }
        return bestMove;
    }

    // 检查是否是制胜移动
    private boolean isWinningMove(int row, int col, int player) {
        board[row][col] = player;
        boolean isWinning = checkWinner(row, col, player);
        board[row][col] = 0;
        return isWinning;
    }

    // 评估位置分数
    private int evaluatePosition(int row, int col) {
        int score = 0;
        board[row][col] = 2;

        // 检查八个方向
        int[][] directions = {
                {-1, 0}, {1, 0},   // 垂直
                {0, -1}, {0, 1},   // 水平
                {-1, -1}, {1, 1},  // 主对角线
                {-1, 1}, {1, -1}   // 副对角线
        };

        // 遍历每个方向
        for (int i = 0; i < directions.length; i += 2) {
            score += evaluateDirection(row, col, directions[i][0], directions[i][1],
                    directions[i+1][0], directions[i+1][1]);
        }

        // 额外的位置策略
        score += evaluatePosition2(row, col);

        board[row][col] = 0;
        return score;
    }

    // 评估某个方向的分数
    private int evaluateDirection(int row, int col, int dir1Row, int dir1Col, int dir2Row, int dir2Col) {
        int count = 1;  // 当前位置算一个
        int empty = 0;  // 空位数量
        int block = 0;  // 被封堵数

        // 检查第一个方向
        for (int i = 1; i <= 4; i++) {
            int newRow = row + dir1Row * i;
            int newCol = col + dir1Col * i;
            if (!isValidPosition(newRow, newCol)) {
                block++;
                break;
            }
            if (board[newRow][newCol] == 2) {
                count++;
            } else if (board[newRow][newCol] == 0) {
                empty++;
                break;
            } else {
                block++;
                break;
            }
        }

        // 检查第二个方向
        for (int i = 1; i <= 4; i++) {
            int newRow = row + dir2Row * i;
            int newCol = col + dir2Col * i;
            if (!isValidPosition(newRow, newCol)) {
                block++;
                break;
            }
            if (board[newRow][newCol] == 2) {
                count++;
            } else if (board[newRow][newCol] == 0) {
                empty++;
                break;
            } else {
                block++;
                break;
            }
        }

        return calculateScore(count, empty, block);
    }

    // 计算具体分数
    private int calculateScore(int count, int empty, int block) {
        if (empty + count >= 5) {
            // 有机会形成五连
            if (count == 4) {
                return block == 0 ? 10000 : 1000; // 活四或冲四
            } else if (count == 3) {
                return block == 0 ? 1000 : 100;   // 活三或眠三
            } else if (count == 2) {
                return block == 0 ? 100 : 10;     // 活二或眠二
            }
        }
        return count;
    }

    // 额外的位置评估策略
    private int evaluatePosition2(int row, int col) {
        int score = 0;

        // 靠近中心的位置分数更高
        int centerDistance = Math.abs(row - 7) + Math.abs(col - 7);
        score += (14 - centerDistance) * 2;

        // 靠近对手棋子的位置分数更高
        if (hasNeighborChess(row, col)) {
            score += 50;
        }

        return score;
    }

    // 检查是否有相邻的棋子
    private boolean hasNeighborChess(int row, int col) {
        for (int i = -2; i <= 2; i++) {
            for (int j = -2; j <= 2; j++) {
                if (i == 0 && j == 0) continue;
                int newRow = row + i;
                int newCol = col + j;
                if (isValidPosition(newRow, newCol) && board[newRow][newCol] != 0) {
                    return true;
                }
            }
        }
        return false;
    }

    // 检查位置是否有效
    private boolean isValidPosition(int row, int col) {
        return row >= 0 && row < MAX_ROW && col >= 0 && col < MAX_COL;
    }

    // 检查是否获胜
    private boolean checkWinner(int row, int col, int chess) {
        // 检查横向
        for (int c = col - 4; c <= col; c++) {
            if (checkLine(row, c, 0, 1, chess)) return true;
        }

        // 检查纵向
        for (int r = row - 4; r <= row; r++) {
            if (checkLine(r, col, 1, 0, chess)) return true;
        }

        // 检查主对角线
        for (int r = row - 4, c = col - 4; r <= row && c <= col; r++, c++) {
            if (checkLine(r, c, 1, 1, chess)) return true;
        }

        // 检查副对角线
        for (int r = row - 4, c = col + 4; r <= row && c >= col; r++, c--) {
            if (checkLine(r, c, 1, -1, chess)) return true;
        }

        return false;
    }

    // 检查一条线上是否有五子连珠
    private boolean checkLine(int row, int col, int rowDir, int colDir, int chess) {
        if (!isValidPosition(row, col) || !isValidPosition(row + 4 * rowDir, col + 4 * colDir)) {
            return false;
        }

        for (int i = 0; i < 5; i++) {
            if (board[row + i * rowDir][col + i * colDir] != chess) {
                return false;
            }
        }
        return true;
    }
}